IndexedDB is a way to store data in the browser.
It lets us store larger amounts of data than local storage in an asynchronous way.
Dexie makes working with IndexedDB easier.
In this article, we’ll take a look at how to start working with IndexedDB with Dexie.
Exception Handling
Exceptions will be handled if they happen in transactions.
For example, we can write:
const db = new Dexie("friends");
db.version(1).stores({
friends: "id, name, *tags"
});
db.transaction('rw', db.friends, () => {
window.MissSpelledVar.NonExistingVar = 3;
}).catch((err) => {
console.error(err);
})
We call catch
to catch the error with trying to access a property of a non-existent property.
If we catch an error within an operation, then the transaction won’t be aborted.
This is because the error is considered to be handled already.
So if we have:
const db = new Dexie("friends");
db.version(1).stores({
friends: "id, name, *tags"
});
db.transaction('rw', db.friends, () => {
db.friends.add({
id: 1,
name: "Foo"
}).catch((e) => {
console.error("Failed to add friend");
});
}).catch((err) => {
console.error(err);
})
Then the inner catch
method would handle any errors with the db.friends.add
call.
If we want to abort the transaction when an error is thrown, we’ve to rethrow the exception.
To do this, we write:
const db = new Dexie("friends");
db.version(1).stores({
friends: "id, name, *tags"
});
db.transaction('rw', db.friends, () => {
db.friends.add({
id: 1,
name: "Foo"
}).catch((e) => {
console.error("Failed to add friend");
throw e;
});
}).catch((err) => {
console.error(err);
})
Collection
Collections represent collections of database objects.
They don’t contain any objects by themselves.
Instead, it yields a preparation for how to run a database query.
Collections return a promise with the data.
Add Multiple Criteria
We can add multiple criteria for our collection with the and
method.
For example, we can write:
const db = new Dexie("friends");
db.version(1).stores({
friends: "id, name, age"
});
(async () => {
await db.friends.put({
id: 1,
name: "jane",
age: 78
});
await db.friends.put({
id: 2,
name: "mary",
age: 76
});
const someFriends = await db.friends
.where("name")
.equalsIgnoreCase("jane")
.and(friends => friends.age > 50)
.toArray()
console.log(someFriends)
})()
We call and
with a callback that returns the condition that we’re looking for to make the query.
Cloning Collections
We can clone a collection with the clone
method.
For example, we can write:
const db = new Dexie("friends");
db.version(1).stores({
friends: "id, name, age"
});
(async () => {
await db.friends.put({
id: 1,
name: "jane",
age: 78
});
await db.friends.put({
id: 2,
name: "mary",
age: 76
});
await db.transaction('r', db.friends, function*() {
const collection = db.friends.where('age').above(75);
const clone = collection.clone().reverse().limit(1);
const allOldFriends = yield collection.toArray();
const oldestFriend = yield clone.toArray();
console.log(allOldFriends)
console.log(oldestFriend)
}).catch(e => {
console.error(e.stack);
});
})()
We added 2 entries to the friends
table.
Then we get all the friends with age
above 75 with:
const collection = db.friends.where('age').above(75);
Then we call clone
to clone the collection with:
const clone = collection.clone().reverse().limit(1);
Then we call toArray
on both to get the results as arrays.
Then we should get the entries from the queries in the console.log
.
Conclusion
We can handle exceptions and do various things with collections with Dexie.